/*
 * shared_buf.hpp
 *
 *  Created on: 2024年3月27日
 *      Author: Dylan.Gao
 */

#ifndef _DM_OS_SHARED_BUF_HPP_
#define _DM_OS_SHARED_BUF_HPP_

#include <dm/os/types.hpp>
#include <dm/bitsref.hpp>
#include <dm/bitinfo.hpp>

namespace dm{
namespace os{

/**
 * 共享缓冲区
 * @tparam TRecord
 * @tparam SizeOfMask
 * @tparam mutex_t
 */
template<typename TRecord,typename TMask=dm::uint8,int SizeOfMask=4,typename mutex_t=upgradable_mutex_t>
struct TSSharedBuf{
	typedef dm::uint32 size_t;

	enum{
		BitsOfMask = dm::TCBitInfo<TMask>::Len,
		SizeOfRecords = SizeOfMask * BitsOfMask
	};

	mutex_t mutex;	// 互斥量,访问对象和函数前都应该加锁
	size_t count;	// 有效记录数,count>SizeOfRecords 表示有后续缓冲区

	TMask masks[SizeOfMask];	// 记录占用位掩码
	TRecord data[SizeOfRecords];	// 数据记录

	/**
	 * 映射到索引
	 * @param buf
	 * @param offset
	 * @return
	 */
	static inline int map2idx( int buf,int offset ){
		return buf*BitsOfMask + offset;
	}

	/**
	 * 通过索引映射到缓冲区索引
	 * @param idx
	 * @return
	 */
	static inline int map2bufIdx( int idx ){
		return idx / BitsOfMask;
	}

	/**
	 * 通过索引映射到缓冲区偏移
	 * @param idx
	 * @return
	 */
	static inline int map2bufOffset(int idx ){
		return idx%BitsOfMask;
	}

    /**
     * @brief 初始化记录
     */
    inline void init(){
        count = 0;
        for( int i=0;i<SizeOfMask;++i )
            masks[i] = dm::TCBitInfo<TMask>::BitsNone;
    }

	/**
	 * 是否满
	 * @return
	 */
	inline bool isFull()const{
		return count >=SizeOfRecords;
	}

	/**
	 * 是否空
	 * @return
	 */
	inline bool isEmpty()const{
		return count==0;
	}

	/**
	 * 是否有后续缓冲区
	 * @return
	 */
	inline bool isOver()const{
		return count > SizeOfRecords;
	}

	/**
	 * 查找第一个空闲节点
	 * @return
	 */
	inline int firstUnmasked()const{
		return nextUnmasked();
	}

	/**
	 * 查找第一个有效记录
	 * @return
	 */
	inline int firstMasked()const{
		return nextMasked();
	}

	/**
	 * 反向查找第一个空闲节点。含指定位置
	 * @param maskIdx
	 * @param maskOffset
	 * @return
	 */
    int lastUnmasked( int maskIdx,int maskOffset )const{
		for( int i=maskIdx;i>=0;--i ){
			if( masks[i]!=TCBitInfo<TMask>::BitsAll ){
				for( int j=(i==maskIdx?maskOffset:BitsOfMask-1);j>=0;--j )
					if( dm::CBitsRef<TMask>(masks[i]).isClr(j) )
						return map2idx(i,j);
			}
		}

		return -1;
	}

	/**
	 * 查找最后一个空闲节点
	 * @return
	 */
	inline int lastUnmasked(int idx=SizeOfRecords-1)const{
		return lastUnmasked(map2bufIdx(idx),map2bufOffset(idx));
	}

	/**
	 * 查找最后一个有效记录
	 * @return
	 */
    int lastMasked( int maskIdx,int maskOffset )const{
		for( int i=maskIdx;i>=0;--i ){
			if( masks[i]!=TCBitInfo<TMask>::BitsNone ){
				for( int j=(i==maskIdx?maskOffset:BitsOfMask-1);j>=0;--j )
					if( dm::CBitsRef<const TMask>(masks[i]).isSet(j) )
						return map2idx(i,j);
			}
		}
		return -1;
	}

    inline int lastMasked( int idx=SizeOfRecords-1 )const{
		return lastMasked(map2bufIdx(idx),map2bufOffset(idx));
	}

	/**
	 * 查找下一个空闲节点
	 * @param idx
	 * @return
	 */
    int nextUnmasked( int maskIdx,int maskOffset )const{
		for( int i=maskIdx;i<SizeOfMask;++i ){
			if( masks[i]!=TCBitInfo<TMask>::BitsAll ){
				for( int j=(i==maskIdx?maskOffset:0);j<BitsOfMask;++j )
                    if( dm::CBitsRef<const TMask>(masks[i]).isClr(j) )
						return map2idx(i,j);
			}
		}

		return -1;
	}

    inline int nextUnmasked( int idx=0 )const{
		return nextUnmasked(map2bufIdx(idx),map2bufOffset(idx));
	}

	/**
	 * 查找下一个有效节点
	 * @param idx 从该节点开始，包含
	 * @return
	 */
    int nextMasked( int maskIdx,int maskOffset )const{
		for( ;maskIdx<SizeOfMask;++maskIdx ){
			if( masks[maskIdx]!=TCBitInfo<TMask>::BitsNone ){
				dm::CBitsRef<const TMask> ref(masks[maskIdx]);
				for( ;maskOffset<BitsOfMask;++maskOffset )
					if( ref.isSet(maskOffset) ){
						return map2idx(maskIdx,maskOffset);
					}
			}
			maskOffset = 0;
		}

		return -1;
	}

    inline int nextMasked( int idx=0 )const{
		return nextMasked(map2bufIdx(idx),map2bufOffset(idx));
	}

	/**
	 * 判断是否有效
	 * @param maskIdx
	 * @param maskOffset
	 * @return
	 */
	inline bool isMasked( int maskIdx,int maskOffset )const{
		return dm::CBitsRef<const TMask>(masks[maskIdx]).isSet(maskOffset);
	}
	/**
	 * 判断是否
	 * @param idx
	 * @return
	 */
	inline bool isMasked( int idx )const{
		return isMasked(map2bufIdx(idx),map2bufOffset(idx));
	}

	inline void mask( int maskIdx,int maskOffset ){
		dm::CBitsRef<TMask>(masks[maskIdx]).set(maskOffset);
	}

	/**
	 * 设置掩码
	 * @param idx
	 */
	inline void mask( int idx ){
		mask(map2bufIdx(idx),map2bufOffset(idx));
	}

	inline void unmask( int maskIdx,int maskOffset ){
		dm::CBitsRef<TMask>(masks[maskIdx]).clr(maskOffset);
	}

	/**
	 * 清除掩码
	 * @param idx
	 */
	inline void unmask( int idx ){
		unmask(map2bufIdx(idx),map2bufOffset(idx));
	}
};

}
}

#endif /* _DM_OS_SHARED_BUF_HPP_ */
